package com.fjzn.detect.config.web.filter;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import org.springframework.http.HttpMethod;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * 构建可重复读取inputStream的request
 * 
 * @author helloworld
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
    private static  final Charset CHARSET = StandardCharsets.UTF_8;

    private byte[] body;

    private Map<String,String[]> parameterMap;

    private  Map<String,String[]> bodyMap;

    public RepeatedlyRequestWrapper(HttpServletRequest request) {
        super(request);
        try {
            body = IoUtil.readBytes(request.getInputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isFormPost() {
        String contentType = this.getContentType();
        return contentType != null && contentType.contains("application/x-www-form-urlencoded") && HttpMethod.POST.matches(this.getMethod());
    }

    public  Map<String,String[]> getBodyparameterMap(){
        initParam();
        return bodyMap;
    }

    @Override
    public String getParameter(String key) {
        initParam();
        String[] values = parameterMap.get(key);
        return values != null && values.length > 0 ? values[0] : null;
    }

    @Override
    public String[] getParameterValues(String key) {
        initParam();
        return parameterMap.get(key);
    }

    @Override
    public Map getParameterMap() {
        initParam();
        return parameterMap;
    }

    private void initParam(){
        if(!isFormPost()){
            parameterMap = new HashMap<>(0);
        }else{
            if (parameterMap == null) {
                Map<String,String[]> result = new HashMap();
                parameterMap = toMap(getQueryString());
                bodyMap = toMap(getPostBodyAsString());
                if(!bodyMap.isEmpty()){
                    parameterMap.putAll(bodyMap);
                }

            }
        }
    }

    private Map<String,String[]> toMap(String body){
        Map<String,String[]> pMap = new HashMap<>();
        if(StrUtil.isNotBlank(body)){
            body = URLUtil.decode(body,CHARSET);
            String[] strArrays = body.split("&");
            if(strArrays.length > 0){
                for(String item : strArrays){
                    String[] oneItme = item.split("=");
                    if(oneItme.length == 2){
                        String key = oneItme[0];
                        String val = oneItme[1];
                        if(pMap.containsKey(key)){
                            String[] src = pMap.get(key);
                            String[] dest = new String[src.length+1];
                            System.arraycopy(src,0,dest,0,src.length);
                            dest[src.length] = val;
                            src = null;
                            pMap.put(key,dest);
                        }else{
                            pMap.put(key,new String[]{val});
                        }
                    }else if(oneItme.length == 1){
                        pMap.put(oneItme[0],null);
                    }
                }
            }
        }
        return pMap;

    }


    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getPostBodyAsString() {
        if(body != null){
            return new String(body,CHARSET);
        }
        return "";
    }

    public byte[] getBody() {
        return this.body;
    }

    // 赋值给body字段
    public void setBody(byte[] body) {
        this.body = body;
    }

    @Override
    public String getCharacterEncoding() {
        String enc = super.getCharacterEncoding();
        return enc != null ? enc : "ISO-8859-1";
    }
}
